package com.example.picturebacked.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.picturebacked.exception.BusinessException;
import com.example.picturebacked.exception.ErrorCode;
import com.example.picturebacked.exception.ThrowUtils;
import com.example.picturebacked.mapper.SpaceMapper;
import com.example.picturebacked.model.dto.space.analyze.*;
import com.example.picturebacked.model.entity.Picture;
import com.example.picturebacked.model.entity.Space;
import com.example.picturebacked.model.entity.User;
import com.example.picturebacked.model.vo.space.analyze.*;
import com.example.picturebacked.service.PictureService;
import com.example.picturebacked.service.SpaceAnalyzeService;
import com.example.picturebacked.service.SpaceService;
import com.example.picturebacked.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Autheor LBT
 */
@Service
public class SpaceAnalyzeServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceAnalyzeService {
    @Resource
    private UserService userService;

    @Resource
    private SpaceService spaceService;

    @Resource
    private PictureService pictureService;

    @Override
    public void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        if (spaceAnalyzeRequest.isQueryAll() || spaceAnalyzeRequest.isQueryPublic()) {
            // 如果想要分析全空间信息或者公共图库信息需要管理员权限
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        } else {
            // 私有空间只有空间管理员才能查看
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR);
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            // 检验是否是空间创建人或者管理员
            spaceService.checkSpaceAuth(space, loginUser);
        }
    }

    @Override
    public SpaceUsageAnalyzeResopnse getSpaceUsageAnalyze(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        if (spaceAnalyzeRequest.isQueryAll() || spaceAnalyzeRequest.isQueryPublic()) {
            // 查看全部图库或者公共图库的使用情况
            // 必须是管理员
            boolean isAdmin = userService.isAdmin(loginUser);
            ThrowUtils.throwIf(!isAdmin, ErrorCode.NO_AUTH_ERROR, "无权访问空间");
            // 统计公共图库的资源使用
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("picSize");
            if (!spaceAnalyzeRequest.isQueryAll()) {
                // 查询全部空间
                queryWrapper.isNull("spaceId");
            }
            List<Object> pictureObjList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            // 将对象转为Long，并计算总和
            long usedSize = pictureObjList.stream().mapToLong(result -> result instanceof Long ? (Long) result : 0)
                    .sum();
            long usedCount = pictureObjList.size();
            // 封装返回结果
            SpaceUsageAnalyzeResopnse spaceUsageAnalyzeResopnse = new SpaceUsageAnalyzeResopnse();
            spaceUsageAnalyzeResopnse.setUsedSize(usedSize);
            spaceUsageAnalyzeResopnse.setMaxSize(null);
            spaceUsageAnalyzeResopnse.setSizeUsageRatio(null);
            spaceUsageAnalyzeResopnse.setUsedCount(usedCount);
            spaceUsageAnalyzeResopnse.setMaxCount(null);
            spaceUsageAnalyzeResopnse.setCountUsageRatio(null);
            return spaceUsageAnalyzeResopnse;
        } else {
            // 查询指定空间
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR);
            // 获取空间信息
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");

            // 校验空间权限，仅空间所有者或管理员可以访问
            spaceService.checkSpaceAuth(space, loginUser);

            // 封装返回结果
            SpaceUsageAnalyzeResopnse spaceUsageAnalyzeResopnse = new SpaceUsageAnalyzeResopnse();
            spaceUsageAnalyzeResopnse.setUsedSize(space.getTotalSize());
            spaceUsageAnalyzeResopnse.setMaxSize(space.getMaxSize());
            spaceUsageAnalyzeResopnse.setUsedCount(space.getTotalCount());
            spaceUsageAnalyzeResopnse.setMaxCount(space.getMaxCount());
            // 直接进行转换成百分数
            // 获取使用大小比例
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize() * 100.0 / space.getMaxSize(), 2).doubleValue();
            // 获取使用数量比例
            double countUsageRatio = NumberUtil.round(space.getTotalCount() * 100.0 / space.getMaxCount(), 2).doubleValue();
            spaceUsageAnalyzeResopnse.setCountUsageRatio(countUsageRatio);
            spaceUsageAnalyzeResopnse.setSizeUsageRatio(sizeUsageRatio);
            return spaceUsageAnalyzeResopnse;
        }
    }

    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceCategoryAnalyzeRequest, loginUser);
        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        // 根据分析范围补充查询条件
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest, queryWrapper);
        // 使用Mybatis-Plus分组查询，查询分类，并计算每个分类的数量，使用category进行分组
        queryWrapper.select("category AS category",
                        "COUNT(*) as count",
                        "SUM(picSize) as totalSize")
                .groupBy("category");
        // 查询并转换结果
        // 在图片表，查询分类，并计算每个分类的数量，使用category进行分组
        List<Map<String, Object>> mapList = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return mapList.stream().map(result -> {
            // 获取到每个图片的分类信息
            String category = result.get("category") != null ? result.get("category").toString() : "未分类";
            // 获取到每个图片的数量
            long count = ((Number) result.get("count")).longValue();
            // 获取到每个图片的总大小
            long totalSize = ((Number) result.get("totalSize")).longValue();
            return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
        }).collect(Collectors.toList());

    }

    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceTagAnalyzeRequest, loginUser);

        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, queryWrapper);

        // 查询所有符合条件的标签
        queryWrapper.select("tags");
        List<String> tagsJsonList =
                // 查询所有的tags标签
                pictureService.getBaseMapper().selectObjs(queryWrapper)
                        .stream()
                        // 过滤掉为null的值
                        .filter(ObjUtil::isNotNull)
                        // 将json对象转为字符串
                        .map(Object::toString)
                        .collect(Collectors.toList());
        // 合并所有标签并统计使用次数
        Map<String, Long> tagCountMap = tagsJsonList.stream().flatMap(
                        tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));
        // 转换为响应对象，按使用次数降序排序
        return tagCountMap.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceSizeAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceSizeAnalyzeRequest, loginUser);
        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest, queryWrapper);
        queryWrapper.select("picSize");
        // 获取所有的图片大小
        List<Long> picSizeList =
                pictureService.getBaseMapper().selectObjs(queryWrapper)
                        .stream()
                        .filter(ObjUtil::isNotNull)
                        .map(obj -> ((Number) obj).longValue())
                        .collect(Collectors.toList());
        // 定义分段范围，注意使用有序map
        Map<String, Long> sizeRanges = new LinkedHashMap<>();
        sizeRanges.put("<100KB", picSizeList.stream().filter(size -> size < 100 * 1024).count());
        sizeRanges.put("100KB-500KB", picSizeList.stream().filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
        sizeRanges.put("500KB-1MB", picSizeList.stream().filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
        sizeRanges.put(">1MB", picSizeList.stream().filter(size -> size >= 1 * 1024 * 1024).count());
        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceUserAnalyzeResponse> getUserUploadAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceUserAnalyzeRequest, loginUser);
        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        Long userId = spaceUserAnalyzeRequest.getUserId();
        ThrowUtils.throwIf(userId == null, ErrorCode.PARAMS_ERROR, "未指定用户");
        queryWrapper.eq("userId", userId);
        fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, queryWrapper);

        // 分析维度：每日、每周、每月
        String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') AS period", "COUNT(*) AS count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) AS period", "COUNT(*) AS count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') AS period", "COUNT(*) AS count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的时间维度");
        }

        queryWrapper.groupBy("period").orderByAsc("period");

        // 查询结果并转换
        List<Map<String, Object>> queryResult = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return queryResult.stream()
                .map(result -> {
                    String period = result.get("period").toString();
                    long count = ((Number) result.get("count")).longValue();
                    return new SpaceUserAnalyzeResponse(period, count);
                }).collect(Collectors.toList());
    }

    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR, "没有权限访问空间排行");
        // 构造查询条件
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        // 仅查询空间id、名称、用户id、总大小，通过总大小进行升序排序，最后获取前N个空间
        queryWrapper.select("id", "spaceName", "userId", "totalSize")
                .orderByDesc("totalSize")
                .last("LIMIT " + spaceRankAnalyzeRequest.getTopN());
        return spaceService.list(queryWrapper);

    }

    /**
     * 根据请求动态添加查询条件
     */
    private static void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
        if (spaceAnalyzeRequest.isQueryAll()) {
            // 查询所有图库
            return;
        }
        if (spaceAnalyzeRequest.isQueryPublic()) {
            // 查询公共图库
            queryWrapper.isNull("spaceId");
            return;
        }
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        if (spaceId != null) {
            queryWrapper.eq("spaceId", spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询范围");
    }
}



























